package com.spzx.product.listener;

import com.rabbitmq.client.Channel;
import com.spzx.common.core.utils.StringUtils;
import com.spzx.product.domain.SkuStockDTO;
import com.spzx.product.mapper.SkuStockMapper;
import com.spzx.common.rabbitmq.cons.SpzxMqCons;
import jakarta.annotation.Resource;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class SpzxProductMqListener {
    @Resource
    RedisTemplate redisTemplate;
    @Resource
    SkuStockMapper skuStockMapper;
    //    @Transactional(rollbackFor = Exception.class)
    @RabbitListener(queues = {SpzxMqCons.SPZX_STOCK_RELEASE_QUEUE})
    public void releaseStock(Channel channel , Message message, String orderNo){

        try {
            //1、消费使用消息 执行业务
            if(StringUtils.isEmpty(orderNo)){
                return;
            }
            Boolean flag = redisTemplate.opsForValue().setIfAbsent("spzx:release:stock:lock:" + orderNo, "1", 2, TimeUnit.MINUTES);
            if(!flag){
                return;
            }
            //获取锁定的库存释放
            Object obj = redisTemplate.opsForValue().get("spzx:product:stock:" + orderNo);
            if(obj==null){
                return;
            }
            List<SkuStockDTO> lockSuccessStockDTOS = (List<SkuStockDTO>) obj;
            if(CollectionUtils.isEmpty(lockSuccessStockDTOS)){
                return;
            }
            //执行释放库存的业务
            lockSuccessStockDTOS.forEach(skuStockDTO -> {
                skuStockMapper.releaseStock(skuStockDTO.getSkuId() , skuStockDTO.getSkuNum());
            });
            //2、手动ACK： 发送消息给rabbitmq，表示消息已经使用完毕 rabbitmq接收到ack后会删除消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            redisTemplate.delete("spzx:release:stock:lock:" + orderNo);
            try {
                if (!message.getMessageProperties().isRedelivered()) {
                    //第一次消费消息时出现异常，尝试让消息归队 重新消费
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                                      false, true);
                    System.out.println("第一次消费消息异常，让消息回到队列中");
                } else {
                    //如果第二次消费同一个消息失败 可以丢弃消息(如果消息所在的队列绑定了死信队列 消息会进入死信队列)
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                    System.out.println("第二次消费消息异常，丢弃消息");
                }
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }

        }finally {

        }
    }

}